﻿//
// © Algobox Ltd - Benn Eichhorn
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Collections.Concurrent;
using Algobox.Objects.Finance.Assets.Stock;
using Algobox.Objects.Finance;
using Algobox.Toolbox.Collections;
using Algobox.Structure.Finance.Strategies.SmartStoploss;
using System.Windows.Data;
using System.Collections.ObjectModel;

namespace Algobox.Structure.Finance.Strategies.Dastan
{
    public class DastanManagement
    {
        #region Constructors

        public DastanManagement(Algobox.Feeds.Finance.MarketData.IMarketFeedAdaptor marketFeed,
            Algobox.Feeds.Finance.Trading.ITradingFeedAdaptor tradingFeed)
        {
            _marketFeed = marketFeed;
            _tradingFeed = tradingFeed;
        }

        #endregion
//////////////////
        #region Member Variables
        
        public readonly static TimeSpan TIME_LAST_ENTRY = TimeSpan.FromHours(16.27); // 16:16:12
        public readonly static TimeSpan TIME_EXIT_ALL = TimeSpan.FromHours(16.45); // 16:27:00

        /// <summary>
        /// Logger used by this class
        /// </summary>        
        private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();
        
        private Algobox.Feeds.Finance.MarketData.IMarketFeedAdaptor _marketFeed;
        private Algobox.Feeds.Finance.Trading.ITradingFeedAdaptor _tradingFeed;
        
        #endregion
//////////////////
        #region Properties

        public bool IsLoaded { get; private set; }
        public bool IsStarted { get; private set; }

        public ConcurrentObservableDictionary<Guid, DastanStock> Strategies { get; set; }
        public ConcurrentObservableDictionary<Strategy, StrategyUnitSummary> ViewUnitSummary { get; set; }
        public ListCollectionView ViewUnits { get; set; }

        #endregion
//////////////////
        #region Functions
        
        public DastanStock AddOrUpdate(
            Guid id,
            StockSecurity security,
            string account,
            int unitValue,
            int numEntryBars,
            int numExitBars,
            int averagePeriod,
            int ticksPerBar)
        {
            // save original settings in TerappinData struct

            // create the view if we are not using a base view created elsewhere
            if (Strategies == null)
            {
                Strategies = new ConcurrentObservableDictionary<Guid, DastanStock>();
            }

            Log.Info("Creating TerrapinStock {0} with a UnitValue({1}), Entry({2}), Exit({3}), FastEMA({4}), SlowSMA({5})", 
                security,
                unitValue,
                numEntryBars,
                numExitBars,
                averagePeriod,
                ticksPerBar);

            // create or update the strategy and add it to the manager dictionary
            DastanStock strategy = Strategies.AddOrUpdate(id,
                (key) =>
                {
                    DastanStock ts = new DastanStock(this,
                        _tradingFeed,
                        security,
                        id,
                        account,
                        unitValue,
                        numEntryBars,
                        numExitBars,
                        averagePeriod,
                        ticksPerBar);

                    _marketFeed.SubscribeLast(security, ts);
                    //_marketFeed.SubscribeBid(security, ts);
                    //_marketFeed.SubscribeAsk(security, ts);

                    return ts;
                },
                (key, inStrategy) =>
                {
                    if (id == inStrategy.DatabaseId)
                    {
                        inStrategy.UnitValue = unitValue;
                        inStrategy.EntryBars = numEntryBars;
                        inStrategy.ExitBars = numExitBars;
                        inStrategy.AveragePeriod = averagePeriod;
                    }                    
                    return inStrategy;
                });

            return strategy;
        }

        public void AddStrategyUnit(DastanUnit unit)
        {
            ((ConcurrentObservableCollection<DastanUnit>)ViewUnits.SourceCollection).Add(unit);

            ViewUnitSummary.AddOrUpdate(unit.Strategy,
                (key) =>
                {
                    StrategyUnitSummary value = new StrategyUnitSummary(key, unit.Name);
                    _marketFeed.SubscribeLast(key.Security, value);
                    value.AddUnit(unit);
                    return value;
                },
                (key, value) =>
                {
                    value.AddUnit(unit);
                    return value;
                });
        }

        public void Remove(DastanStock strategy)
        {
            _marketFeed.UnsubscribeLast(strategy.Security, strategy);
            //_marketFeed.UnsubscribeBid(strategy.Value.Security, strategy.Value);
            //_marketFeed.UnsubscribeAsk(strategy.Value.Security, strategy.Value);

            strategy.ExitUnit(DateTime.Now);
            Strategies.TryRemove(strategy.DatabaseId);
        }

        public void RemoveAll()
        {
            foreach (KeyValuePair<Guid, DastanStock> strategy in Strategies)
            {
                _marketFeed.UnsubscribeLast(strategy.Value.Security, strategy.Value);
                //_marketFeed.UnsubscribeBid(strategy.Value.Security, strategy.Value);
                //_marketFeed.UnsubscribeAsk(strategy.Value.Security, strategy.Value);
            }
            Strategies.Clear();
        }
        

        #endregion
//////////////////
        #region Enums


        #endregion

    }
}